Lambda(Python3.6)でDynamoDBに登録された項目が日付型であるかチェックしてみる
どうも!大阪オフィスの西村祐二です。
DynamoDBで提供されている属性の型は大きく分けて スカラー型、ドキュメント型、セット型となっています。
そのため、下記画像のように日付と時刻を登録するときは文字列データ型(String型)を使用するのがほとんどだと思います。
ただ、こちらが想定するフォーマット以外でも登録することができてしまい、 登録された時刻をみて、ある処理を実行するときなど 処理が失敗してしまう可能性があります。
今回はLambdaを使って登録されている項目のフォーマットが正しいかチェックしてみたいと思います。
DynamoDBのテーブル作成
今回はCloudFormationを使ってDynamoDBのテーブルを作成します。
テンプレートファイルを作成します。 今回作成するテーブルはプライマリーキー「Date」、ソートキー「Time」とし、 属性のデータ型を文字列データの「S」として設定しています。
$ vi dynamodb.yml
--- AWSTemplateFormatVersion: "2010-09-09" Resources: myDynamoDBTable: Type: "AWS::DynamoDB::Table" Properties: TableName: "dynamo-test" AttributeDefinitions: - AttributeName: Date AttributeType: S - AttributeName: Time AttributeType: S KeySchema: - AttributeName: Date KeyType: HASH - AttributeName: Time KeyType: RANGE ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1
下記コマンドにてテーブルを作成します。
$ aws cloudformation validate-template --template-body file://dynamodb.yml $ aws cloudformation create-stack dynamodb-test --template-body file://dynamodb.yml
成功したら下記画像のように作成されているはずです。
Lambda関数の作成
AWS Management Consoleにログインして、AWS Lambda Dashboardを開きます。
Lambda関数一覧の画面で、[関数の作成]ボタンをクリックします。
[一から作成]ボタンをクリックします。
名前を[dynamodb-check]とし、
ロールにはDynamoDBのテーブルをスキャンするので
"dynamodb:Scan"
を付与しておいてください。
[関数の作成]ボタンをクリックします。
移動した画面で、ランタイムのドロップダウンリストからPython 3.6を選択します。 下記、プログラムをコピペし、保存ボタンをクリックします。
import boto3 import logging from datetime import datetime # dynamodb DYNAMO_TABLE_NAME = 'dynamodb-test' dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(DYNAMO_TABLE_NAME) def format_check(data): try: for i in range(len(data)): dynamo_datetime = str(data[i]['Date'])+ " " + str(data[i]['Time']) ## 日時フォーマットに変換 (ex:2017-10-19 01:01) get_datetime = datetime.strptime(dynamo_datetime, '%Y-%m-%d %H:%M') print(get_datetime) print('ok') except Exception as e: logger.exception("{}".format(e)) return "ERROR End" def handler(event, context): try: response = table.scan() data = response['Items'] format_check(data) except Exception as e: logger.exception("{}".format(e)) return "ERROR End"
簡単に解説します。 ポイントは15行目です。
get_datetime = datetime.strptime(dynamo_datetime, '%Y-%m-%d %H:%M')
pythonのdatetime.strptime
はかなり便利で、
日付や時刻に対応する書式文字列から datetime オブジェクトに変換してくれます。
また、strptimeの第二引数は第一引数のフォーマットを渡すため、 これにマッチしないとエラーとなります。 ここでエラーになるということは、つまり、想定しないフォーマットで入力されていることになります。
今回の場合は Date:2017-10-19 のような日付 Time:01:01 のような時刻が 入力されている想定です。
また、入力してほしいフォーマットが
Date:2017/10/19
のような日付の場合は
第二引数を%Y/%m/%d
のように対応する形に変更すれば、OKです。
get_datetime = datetime.strptime(dynamo_datetime, '%Y/%m/%d %H:%M')
動作確認
DynamoDBにいろいろなデータをいれて、 動作を確認してみたいと思います。
正しいフォーマットでいれてみる
[項目の作成]をクリックして、 Date:2017-10-20 Time:20:20 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され問題なく、変換できていることがわかります。
時刻を一桁のままでいれてみる
[項目の作成]をクリックして、 Date:2017-10-20 Time:1:1 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され問題なく、変換できていることがわかります。
全角を入れてみる
[項目の作成]をクリックして、 Date:2017−10−20 Time:20:20 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され想定どおり、エラー出力ができていることがわかります。
ありえない日程をいれてみる
[項目の作成]をクリックして、 Date:2017-15-10 Time:20:20 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され想定どおり、エラー出力ができていることがわかります。
ありえない時刻をいれてみる
[項目の作成]をクリックして、 Date:2017-10-20 Time:25:20 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され想定どおり、エラー出力ができていることがわかります。
追加で、 Date:2017-10-20 Time:20:80 を登録してみました。
作成したLambda関数を実行させてみると
下記ログが出力され
今回はなぜかunconverted data
というようなエラーが出力されました。
さいごに
いかがだったでしょうか。 Lambdaをつかって DynamoDBに登録された項目が日付型であるかチェックしてみました。 あとは、Lambdaで定期的に確認しエラーが出力されれば ユーザにメールを送信すればとりあえずは良いかと思います。 もっといいやり方があれば教えてください。
誰かのためになれば幸いです。